package com.tianxiabuyi;

import java.sql.CallableStatement;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.ResultSetMetaData;
import java.sql.SQLException;
import java.sql.Types;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import com.alibaba.fastjson.JSON;
/**
 * 原生jdbc公共方法，适用自定义存储过程和函数、sql实现调用，不做过多封装
* @ClassName: JDBCUtil 
* @Description: TODO(这里用一句话描述这个类的作用) 
* @author jacking
* @date 2018年5月31日 下午2:29:54 
*
 */
public class JDBCUtil {
	private static Connection conn = null;
	private static ResultSet rs = null;
	private static PreparedStatement ps = null;
	private static  CallableStatement calls = null;
	private static JDBCUtil jc = null;

	private static String driver = "com.microsoft.sqlserver.jdbc.SQLServerDriver";
	private static String url = "jdbc:sqlserver://192.168.2.72:1433;databaseName=THIS4";
	private static String userName = "user";
	private static String passwrod = "123456";

	private JDBCUtil() {
	}
/**
 * 根据参数获取对象
* @Title: getInstance 
* @Description: TODO(这里用一句话描述这个方法的作用) 
* @param @param driver
* @param @param url
* @param @param userName
* @param @param passwrod
* @param @return    设定文件 
* @return JDBCUtil    返回类型 
* @throws
 */
	public synchronized static JDBCUtil getInstance(String driver, String url, String userName, String passwrod) {
		if (jc == null) {
			setDriver(driver);
			setUrl(url);
			setUserName(userName);
			setPasswrod(passwrod);
			jc = new JDBCUtil();
		}
		if(driver!=null&&!driver.equals(JDBCUtil.driver)){
			setDriver(driver);
		}
		if(url!=null&&!url.equals(JDBCUtil.url)){
			setUrl(url);
		}
		if(userName!=null&&!userName.equals(JDBCUtil.userName)){
			setUserName(userName);
		}
		if(passwrod!=null&&!passwrod.equals(JDBCUtil.passwrod)){
			setPasswrod(passwrod);
		}

		return jc;
	}

	public synchronized static JDBCUtil getInstance() {
		if (jc == null) {
				setDriver(driver);
				setUrl(url);
				setUserName(userName);
				setPasswrod(passwrod);
				jc = new JDBCUtil();
			jc = new JDBCUtil();
		}
		return jc;
	}

	private static Connection getConnection() {
		try {
			Class.forName(driver);
			conn = DriverManager.getConnection(url, userName, passwrod);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return conn;
	}
     /**
      * 根据sql占位查询数据数据列表
     * @Title: findListBySql 
     * @Description: TODO(这里用一句话描述这个方法的作用) 
     * @param @param sql 例 select * from where user name=?  and age=20;
     * @param @param params
     * @param @return    设定文件 
     * @return List<Map<String,Object>>    返回类型 
     * @throws
      */
	public static List<Map<String, Object>> findListBySql(String sql, List<String> params) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		try {
			conn = getConnection();
			ps = conn.prepareStatement(sql);
			if (params != null) {
				for (int i = 0; i < params.size(); i++) {
					ps.setObject(i+1, params.get(i));
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_name = rsmd.getColumnName(i + 1);
					Object col_value = rs.getObject(col_name);
					if (col_value == null) {
						col_value = "";
					}
					map.put(col_name, col_value);
				}
				mapList.add(map);
			}
			return mapList;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	/**
	 * 根据sql占位查询Map数据(聚合函数请指定列名)
	 * @Title: findListBySql 
	 * @Description: TODO(这里用一句话描述这个方法的作用) 
	 * @param @param sql 例 select * from where user name=?  and age=20;
	 * @param @param params
	 * @param @return    设定文件 
	 * @return List<Map<String,Object>>    返回类型 
	 * @throws
	 */
	public static Map<String, Object> findListBySqlUnique(String sql, List<String> params) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		try {
			conn = getConnection();
			ps = conn.prepareStatement(sql);
			if (params != null) {
				for (int i = 0; i < params.size(); i++) {
					ps.setObject(i+1, params.get(i));
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_name = rsmd.getColumnName(i + 1);
					Object col_value = rs.getObject(col_name);
					if (col_value == null) {
						col_value = "";
					}
					map.put(col_name, col_value);
				}
				mapList.add(map);
			}
			
			return mapList.size()>0?mapList.get(0):null;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	/**
	 * 执行sql返回map(须指定列名)
	* @Title: executeBySqlMap 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param @param sql
	* @param @param params
	* @param @return    设定文件 
	* @return Map<String,Object>    返回类型 
	* @throws
	 */
	public static Map<String, Object> executeBySqlMap(String sql, List<String> params) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		try {
			conn = getConnection();
			ps = conn.prepareStatement(sql);
			if (params != null) {
				for (int i = 0; i < params.size(); i++) {
					ps.setObject(i+1, params.get(i));
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			while (rs.next()) {
				Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_name = rsmd.getColumnName(i + 1);
					Object col_value = rs.getObject(col_name);
					if (col_value == null) {
						col_value = "";
					}
					map.put(col_name, col_value);
				}
				mapList.add(map);
			}
			return mapList.size()>0?mapList.get(0):null;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	/**
	 * 执行sql返回List未列名的字段
	* @Title: executeBySqlArray 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param @param sql
	* @param @param params
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static List<String>  executeBySqlArray(String sql, List<String> params) {
		List<String> list = new ArrayList();
		try {
			conn = getConnection();
			ps = conn.prepareStatement(sql);
			if (params != null) {
				for (int i = 0; i < params.size(); i++) {
					ps.setObject(i+1, params.get(i));
				}
			}
			rs = ps.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			while (rs.next()) {
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_value =rs.getString(i+1);
					if (col_value == null) {
						col_value = "";
					}
					list.add(col_value);
				}
				
			}
			return list;
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	/**
	 * 执行sql返回true为成功
	* @Title: executeBySql 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param @param sql
	* @param @param params
	* @param @return    设定文件 
	* @return boolean    返回类型 
	* @throws
	 */
		public static boolean executeBySql(String sql, List<String> params) {
			boolean flag=false;
			try {
				conn = getConnection();
				ps = conn.prepareStatement(sql);
				if (params != null) {
					for (int i = 0; i < params.size(); i++) {
						ps.setObject(i+1, params.get(i));
					}
				}
				flag=  ps.execute();
			return flag;
			} catch (SQLException e) {
				e.printStackTrace();
				return flag;
			} finally {
				close();
			}
	}
	/**
	 * 调用存储过程或函数返回指定列名的字段
	 * {? = call procedureName(?,?,?)} or {call procedureName(?,?,?)}
	* @Title: findListByCall 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param @param callsql
	* @param @param params
	* @param @return    设定文件 
	* @return List<Map<String,Object>>    返回类型 
	* @throws
	 */
	public static  Map executeByCallMap(String callsql, List<String> params) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		try {
			conn = getConnection();
			calls = conn.prepareCall(callsql); 
			if (params != null) {
				for (int i = 0; i < params.size(); i++) {
						calls.setString(i+1, params.get(i));
				}
			}
			rs = calls.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
	      while (rs.next()) {
	    	  Map<String, Object> map = new HashMap<String, Object>();
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_name = rsmd.getColumnName(i + 1);
					Object col_value = rs.getObject(col_name);
					if (col_value == null) {
						col_value = "";
					}
					map.put(col_name, col_value);
				}
				
				mapList.add(map);
			}
	      return mapList.size()>0?mapList.get(0):null;
			
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	/**
	 * 调用存储过程或函数返回没有指定列名的字段
	 * {? = call procedureName(?,?,?)} or {call procedureName(?,?,?)}
	* @Title: executeByCallArray 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param @param callsql
	* @param @param params
	* @param @return    设定文件 
	* @return List<String>    返回类型 
	* @throws
	 */
	public static  List<String>  executeByCallArray(String callsql, List<String> params) {
		 List<String> list = new ArrayList<>();
		try {
			conn = getConnection();
			calls = conn.prepareCall(callsql); 
			if (params != null) {
				for (int i = 0; i < params.size(); i++) {
					calls.setString(i+1, params.get(i));
				}
			}
			rs = calls.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			while (rs.next()) {
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_value =rs.getString(i+1);
					if (col_value == null) {
						col_value = "";
					}
					list.add(col_value);
				}
				
			}
			return list;
			
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	
	 
	 /**
	  * 调用存储过程或函数返回为指定列名的数据列表
	  * {? = call procedureName(?,?,?)} or {call procedureName(?,?,?)}
	 * @Title: findListByCall 
	 * @Description: TODO(这里用一句话描述这个方法的作用) 
	 * @param @param callsql
	 * @param @param params
	 * @param @return    设定文件 
	 * @return List<Map<String,Object>>    返回类型 
	 * @throws
	  */
	public static List<Map<String, Object>> findListByCall(String callsql, List<String> params) {
		List<Map<String, Object>> mapList = new ArrayList<Map<String, Object>>();
		try {
			conn = getConnection();
			calls = conn.prepareCall(callsql); 
			if (params != null) {
				calls.registerOutParameter(1, Types.INTEGER);
				for (int i = 0; i < params.size(); i++) {
					calls.setString(i+2, params.get(i));
				}
			}
			rs = calls.executeQuery();
			ResultSetMetaData rsmd = rs.getMetaData();
			Map<String, Object> map = null;
			while (rs.next()) {
				map = new HashMap<String, Object>();
				for (int i = 0; i < rsmd.getColumnCount(); i++) {
					String col_name = rsmd.getColumnName(i + 1);
					Object col_value = rs.getObject(col_name);
					if (col_value == null) {
						col_value = "";
					}
					map.put(col_name, col_value);
				}
				mapList.add(map);
			}
			return mapList;
			
		} catch (SQLException e) {
			e.printStackTrace();
			return null;
		} finally {
			close();
		}
	}
	
	/**
	 * 关闭连接
	* @Title: close 
	* @Description: TODO(这里用一句话描述这个方法的作用) 
	* @param     设定文件 
	* @return void    返回类型 
	* @throws
	 */
	private static void close(){
		try {
			if (rs != null) rs.close(); 
			if (ps != null) ps.close(); 
			if (calls != null) calls.close(); 
			if (conn != null) conn.close(); 
		} catch (Exception e) {
			e.printStackTrace();
		}
		
		
	}

	/**
	 * @return driver
	 */
	private static String getDriver() {
		return driver;
	}

	/**
	 * @param driver
	 *            要设置的 driver
	 */
	private static void setDriver(String driver) {
		JDBCUtil.driver = driver;
	}

	/**
	 * @return url
	 */
	private static String getUrl() {
		return url;
	}

	/**
	 * @param url
	 *            要设置的 url
	 */
	private static void setUrl(String url) {
		JDBCUtil.url = url;
	}

	/**
	 * @return userName
	 */
	private static String getUserName() {
		return userName;
	}

	/**
	 * @param userName
	 *            要设置的 userName
	 */
	public static void setUserName(String userName) {
		JDBCUtil.userName = userName;
	}

	/**
	 * @return passwrod
	 */
	private static String getPasswrod() {
		return passwrod;
	}

	/**
	 * @param passwrod
	 *            要设置的 passwrod
	 */
	private static void setPasswrod(String passwrod) {
		JDBCUtil.passwrod = passwrod;
	}
/*	public static void main(String[] args) {
		JDBCUtil jc=JDBCUtil.getInstance();
		String sql="SELECT  top 10  t1.sfzh,t1.sfzly,t1.lrrq '录入日期',t2.* from SF_BRXXK t1,GH_SH_GHYYK t2 WHERE t1.patid=t2.patid and t1.sfzh='31010319780703202X' and djbz=0 ";
		sql="SELECT    t1.sfzh,t1.sfzly,t1.lrrq '录入日期',t2.* from SF_BRXXK t1,GH_SH_GHYYK t2 WHERE t1.patid=t2.patid and t1.sfzh='31010319780703202X' and djbz=? ";
		List<String> params=new ArrayList<>();
		
		String callsql="";
		
		
		
		callsql="{call 写病人基本信息(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}";
		params.add("91000008");//病人病历号
		params.add("看看");//姓名
		params.add("00");//操作员(最好就用00，这是系统超级用户)
		params.add("1");//卡类别	1:磁卡
		params.add("91000008");//卡号
		params.add("");//个人医保号
		params.add("");//单位医保号
		params.add("");//社保号
		params.add("");//其它卡号
		params.add("31010319780703202X");//身份证号（必填）
		params.add("女");//性别
		params.add("19780703");//出生年月
		params.add("无锡市大成路1号402室");//联系地址（必填）
		params.add("13585717313");//联系电话（必填
		params.add("");//邮政编码
		params.add("");//联系人
		params.add("1");//医保代码（固定）
		params.add("");//凭证号
		params.add("");//单位代码 
		params.add("");//单位名称
		params.add("");//区县代码
		params.add("");//开始日期
		params.add("");//结束日期
		params.add("");//医疗项目
		params.add("");//诊断代码
		params.add("0");//帐户金额
		params.add("");//备注
		
		
		
		List<String>   data=jc.executeByCallArray(callsql, params);
		System.out.println(JSON.toJSON(data)); 
		
		  params=new ArrayList<>();
		  params.add("1021");
		  params.add("20180518");
		  params.add("20180601");
		  callsql="{? = call 获取科室预约信息(?,?,?)}";
		 List  data=jc.findListByCall(callsql, params); 
		System.out.println(JSON.toJSON(data)); 
		
		  params=new ArrayList<>();
		  params.add("0");
	 	List  data=jc.findListBySql(sql, params);
		System.out.println(JSON.toJSON(data)); 
		
	}
	@Test
*/	public  void Testmain() {
		JDBCUtil jc=JDBCUtil.getInstance();
		String sql="SELECT  top 10  t1.sfzh,t1.sfzly,t1.lrrq '录入日期',t2.* from SF_BRXXK t1,GH_SH_GHYYK t2 WHERE t1.patid=t2.patid and t1.sfzh='31010319780703202X' and djbz=0 ";
		  sql="SELECT    t1.sfzh,t1.sfzly,t1.lrrq '录入日期',t2.* from SF_BRXXK t1,GH_SH_GHYYK t2 WHERE t1.patid=t2.patid and t1.sfzh='31010319780703202X' and djbz=? ";
		  List<String> params=new ArrayList<>();
		 
		  String callsql="";
		  
		  
		  callsql="{call 写病人基本信息(?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)}";
		  params.add("91000008");//病人病历号
		  params.add("看看");//姓名
		  params.add("00");//操作员(最好就用00，这是系统超级用户)
		  params.add("1");//卡类别	1:磁卡
		  params.add("91000008");//卡号
		  params.add("");//个人医保号
		  params.add("");//单位医保号
		  params.add("");//社保号
		  params.add("");//其它卡号
		  params.add("31010319780703202X");//身份证号（必填）
		  params.add("女");//性别
		  params.add("19780703");//出生年月
		  params.add("无锡市大成路1号402室");//联系地址（必填）
		  params.add("13585717313");//联系电话（必填
		  params.add("");//邮政编码
		  params.add("");//联系人
		  params.add("1");//医保代码（固定）
		  params.add("");//凭证号
		  params.add("");//单位代码 
		  params.add("");//单位名称
		  params.add("");//区县代码
		  params.add("");//开始日期
		  params.add("");//结束日期
		  params.add("");//医疗项目
		  params.add("");//诊断代码
		  params.add("0");//帐户金额
		  params.add("");//备注
		  
		  
		  
		  List<String>   data=jc.executeByCallArray(callsql, params);
	     System.out.println(JSON.toJSON(data)); 
		  
		/*  params=new ArrayList<>();
		  params.add("1021");
		  params.add("20180518");
		  params.add("20180601");
		  callsql="{? = call 获取科室预约信息(?,?,?)}";
		 List  data=jc.findListByCall(callsql, params); 
		System.out.println(JSON.toJSON(data)); */
		  
		/*  params=new ArrayList<>();
		  params.add("0");
	 	List  data=jc.findListBySql(sql, params);
		System.out.println(JSON.toJSON(data)); */
		
	}

}